﻿#include "websocketclient.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QCryptographicHash>

WebSocketClient::WebSocketClient(QObject *parent) : QObject(parent), m_connected(false), m_firmwareUploadCompleted(false)
{
    // Connect WebSocket signals and slots
    connect(&m_webSocket, &QWebSocket::connected, this, &WebSocketClient::onConnected);
    connect(&m_webSocket, &QWebSocket::disconnected, this, &WebSocketClient::onDisconnected);
    connect(&m_webSocket, &QWebSocket::textMessageReceived, this, &WebSocketClient::onTextMessageReceived);
    connect(&m_webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error), this,
            &WebSocketClient::onError);
}

WebSocketClient::~WebSocketClient()
{
    disconnectFromServer();
}

void WebSocketClient::connectToServer(const QString &url)
{
    if (m_webSocket.state() == QAbstractSocket::ConnectedState) {
        return;
    }

    m_webSocket.open(QUrl(url));
}

void WebSocketClient::disconnectFromServer()
{
    if (m_webSocket.state() != QAbstractSocket::UnconnectedState) {
        m_webSocket.close();
    }
}

void WebSocketClient::requestRtspUrl(const QString &cameraId)
{
    if (!m_connected) {
        emit errorOccurred(QString("WebSocket not connected"));
        return;
    }

    // Create request ID
    QString requestId = QUuid::createUuid().toString(QUuid::WithoutBraces);

    // Create JSON-RPC request
    QJsonObject request;
    request["id"] = requestId;
    request["method"] = "cameras.getStream";

    int32_t cameraIdInt = cameraId.toInt();
    QJsonObject params;
    params["channel"] = cameraIdInt;
    params["stream_type"] = 0;
    params["protocol"] = "rtsp";
    request["params"] = params;

    // Save request ID and camera ID mapping
    m_pendingRequests[requestId] = cameraId;

    // Send request
    QJsonDocument doc(request);
    m_webSocket.sendTextMessage(doc.toJson(QJsonDocument::Compact));
}

void WebSocketClient::sendMessage(const QString &message)
{
    if (!m_connected) {
        emit errorOccurred(QString("WebSocket not connected"));
        return;
    }

    m_webSocket.sendTextMessage(message);
}

bool WebSocketClient::isConnected() const
{
    return m_connected;
}

void WebSocketClient::onConnected()
{
    m_connected = true;
    emit connectionStateChanged(true);
}

void WebSocketClient::onDisconnected()
{
    m_connected = false;
    emit connectionStateChanged(false);
}

void WebSocketClient::onTextMessageReceived(const QString &message)
{
    // Send raw message signal
    emit textMessageReceived(message);

    QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8());
    if (doc.isNull() || !doc.isObject()) {
        return;
    }

    QJsonObject obj = doc.object();

    // Check if it's a response message
    if (obj.contains("id") && obj.contains("result")) {
        QString id = obj["id"].toString();

        // Check if it's a pending request
        if (m_pendingRequests.contains(id)) {
            QString requestType = m_pendingRequests[id];
            QJsonObject result = obj["result"].toObject();

            // 处理不同类型的响应
            if (requestType == "challenge") {
                // 挑战码响应
                if (result.contains("challenge") && result.contains("expires_in")) {
                    QString challenge = result["challenge"].toString();
                    int expiresIn = result["expires_in"].toInt();
                    emit challengeReceived(challenge, expiresIn);
                }
            } else if (requestType == "login") {
                // 登录响应
                if (result.contains("access_token") && result.contains("refresh_token")) {
                    QString accessToken = result["access_token"].toString();
                    QString refreshToken = result["refresh_token"].toString();
                    QJsonObject userInfo = result.contains("user") ? result["user"].toObject() : QJsonObject();
                    emit loginSuccess(accessToken, refreshToken, userInfo);
                }
            } else if (requestType == "refreshToken") {
                // 刷新令牌响应
                if (result.contains("access_token")) {
                    QString accessToken = result["access_token"].toString();
                    QString refreshToken = result.contains("refresh_token") ? result["refresh_token"].toString() : "";
                    QJsonObject emptyObj;
                    emit loginSuccess(accessToken, refreshToken, emptyObj);
                }
            } else if (requestType == "getNetworkConfig") {
                // 网络配置获取响应
                emit networkConfigReceived(result);
            } else if (requestType == "setNetworkConfig") {
                // 网络配置设置响应
                bool success = result.contains("status") && result["status"].toString() == "success";
                QString message = result.contains("message") ? result["message"].toString() : 
                                (success ? "网络配置设置成功" : "网络配置设置失败");
                emit networkConfigSetResult(success, message);
            } else if (requestType == "uploadFirmware") {
                // 固件上传响应
                if (result.contains("progress")) {
                    int progress = result["progress"].toInt();
                    emit firmwareUploadProgress(progress);
                    
                    // 如果上传进度为100%且尚未触发完成信号，表示上传完成
                    if (progress >= 100 && !m_firmwareUploadCompleted) {
                        m_firmwareUploadCompleted = true;
                        emit firmwareUploadComplete();
                    }
                }
            } else if (requestType == "startFirmwareUpgrade") {
                // 固件升级开始响应
                if (result.contains("status")) {
                    QString upgradeId = result["upgrade_id"].toString();
                    QString status = result["status"].toString();
                    int estimatedDuration = result.contains("estimated_duration") ? result["estimated_duration"].toInt() : 0;
                    emit firmwareUpgradeStarted(upgradeId, status, estimatedDuration);
                }
            } else if (requestType == "getFirmwareUpgradeStatus") {
                // 固件升级状态响应
                if (result.contains("status")) {
                    QString status = result["status"].toString();
                    int progress = result.contains("progress") ? result["progress"].toInt() : 0;
                    QString message = result.contains("message") ? result["message"].toString() : "";
                    emit firmwareUpgradeStatusReceived(status, progress, message);
                }
            } else if (result.contains("url")) {
                // RTSP URL响应
                QString url = result["url"].toString();
                QString expiresAt = result.contains("expires_at") ? result["expires_at"].toString() : "";

                // Send RTSP URL signal
                emit rtspUrlReceived(url, expiresAt);
            }

            // Remove pending request
            m_pendingRequests.remove(id);
        }
    }
    // Check if it's an error message
    else if (obj.contains("id") && obj.contains("error")) {
        QString id = obj["id"].toString();
        QJsonObject error = obj["error"].toObject();

        int errorCode = error.contains("code") ? error["code"].toInt() : 0;
        QString errorMessage = error.contains("message") ? error["message"].toString() : QString("Unknown error");

        // 如果是登录相关请求的错误，发送登录失败信号
        if (m_pendingRequests.contains(id)) {
            QString requestType = m_pendingRequests[id];
            if (requestType == "challenge" || requestType == "login" || requestType == "refreshToken") {
                emit loginFailed(errorCode, errorMessage);
            } else if (requestType == "uploadFirmware" || requestType == "startFirmwareUpgrade") {
                emit firmwareUpgradeError(errorMessage);
            } else if (requestType == "getFirmwareUpgradeStatus") {
                // 对于状态查询错误，如果是"No upgrade in progress"，可能意味着升级已完成
                if (errorMessage.contains("No upgrade in progress") || errorMessage.contains("升级完成失败")) {
                    // 这种情况下，可能升级已经成功完成，发送成功状态
                    emit firmwareUpgradeStatusReceived("completed", 100, "升级已完成");
                } else {
                    emit firmwareUpgradeError(errorMessage);
                }
            } else {
                emit errorOccurred(errorMessage);
            }
        } else {
            emit errorOccurred(errorMessage);
        }

        // Remove pending request
        if (m_pendingRequests.contains(id)) {
            m_pendingRequests.remove(id);
        }
    }
}

void WebSocketClient::onError(QAbstractSocket::SocketError error)
{
    Q_UNUSED(error);
    emit errorOccurred(QString("WebSocket error: ") + m_webSocket.errorString());
}

void WebSocketClient::requestChallenge(const QString &username, const QString &deviceId)
{
    if (!m_connected) {
        emit errorOccurred("未连接到服务器");
        return;
    }

    // 创建请求ID
    QString requestId = QUuid::createUuid().toString(QUuid::WithoutBraces);

    // 创建请求JSON对象
    QJsonObject requestObj;
    requestObj["id"] = requestId;
    requestObj["method"] = "auth.getChallenge";

    QJsonObject paramsObj;
    paramsObj["username"] = username;
    paramsObj["device_id"] = deviceId;
    requestObj["params"] = paramsObj;

    // 转换为JSON文档
    QJsonDocument doc(requestObj);
    QString message = doc.toJson(QJsonDocument::Compact);

    // 记录这是一个挑战码请求
    m_pendingRequests[requestId] = "challenge";

    // 发送请求
    m_webSocket.sendTextMessage(message);
}

void WebSocketClient::login(const QString &username,
                            const QString &challenge,
                            const QString &credential,
                            const QString &deviceId,
                            bool rememberMe)
{
    if (!m_connected) {
        emit errorOccurred("未连接到服务器");
        return;
    }

    // 创建请求ID
    QString requestId = QUuid::createUuid().toString(QUuid::WithoutBraces);

    // 创建请求JSON对象
    QJsonObject requestObj;
    requestObj["id"] = requestId;
    requestObj["method"] = "auth.login";

    QJsonObject paramsObj;
    paramsObj["username"] = username;
    paramsObj["challenge"] = challenge;
    paramsObj["credential"] = credential;
    paramsObj["device_id"] = deviceId;

    // 设备信息
    QJsonObject deviceInfoObj;
    deviceInfoObj["type"] = "desktop";
    deviceInfoObj["os"] = "Windows";
    deviceInfoObj["client"] = "Open IPC PC Client";
    paramsObj["device_info"] = deviceInfoObj;

    paramsObj["remember_me"] = rememberMe;

    requestObj["params"] = paramsObj;

    // 转换为JSON文档
    QJsonDocument doc(requestObj);
    QString message = doc.toJson(QJsonDocument::Compact);

    // 记录这是一个登录请求
    m_pendingRequests[requestId] = "login";

    // 发送请求
    m_webSocket.sendTextMessage(message);
}

void WebSocketClient::refreshToken(const QString &refreshToken, const QString &deviceId)
{
    if (!m_connected) {
        emit errorOccurred("未连接到服务器");
        return;
    }

    // 创建请求ID
    QString requestId = QUuid::createUuid().toString(QUuid::WithoutBraces);

    // 创建请求JSON对象
    QJsonObject requestObj;
    requestObj["id"] = requestId;
    requestObj["method"] = "auth.refreshToken";

    QJsonObject paramsObj;
    paramsObj["refresh_token"] = refreshToken;
    paramsObj["device_id"] = deviceId;
    requestObj["params"] = paramsObj;

    // 转换为JSON文档
    QJsonDocument doc(requestObj);
    QString message = doc.toJson(QJsonDocument::Compact);

    // 记录这是一个刷新令牌请求
    m_pendingRequests[requestId] = "refreshToken";

    // 发送请求
    m_webSocket.sendTextMessage(message);
}

void WebSocketClient::logout(const QString &deviceId, bool logoutAll)
{
    if (!m_connected) {
        emit errorOccurred("未连接到服务器");
        return;
    }

    // 创建请求ID
    QString requestId = QUuid::createUuid().toString(QUuid::WithoutBraces);

    // 创建请求JSON对象
    QJsonObject requestObj;
    requestObj["id"] = requestId;
    requestObj["method"] = "auth.logout";

    QJsonObject paramsObj;
    paramsObj["device_id"] = deviceId;
    paramsObj["logout_all"] = logoutAll;
    requestObj["params"] = paramsObj;

    // 转换为JSON文档
    QJsonDocument doc(requestObj);
    QString message = doc.toJson(QJsonDocument::Compact);

    // 记录这是一个登出请求
    m_pendingRequests[requestId] = "logout";

    // 发送请求
    m_webSocket.sendTextMessage(message);
}

void WebSocketClient::getNetworkConfig()
{
    if (!m_connected) {
        emit errorOccurred("未连接到服务器");
        return;
    }

    // 创建请求ID
    QString requestId = QUuid::createUuid().toString(QUuid::WithoutBraces);

    // 创建请求JSON对象
    QJsonObject requestObj;
    requestObj["id"] = requestId;
    requestObj["method"] = "network.getConfig";
    requestObj["params"] = QJsonObject();

    // 转换为JSON文档
    QJsonDocument doc(requestObj);
    QString message = doc.toJson(QJsonDocument::Compact);

    // 记录这是一个网络配置获取请求
    m_pendingRequests[requestId] = "getNetworkConfig";

    // 发送请求
    m_webSocket.sendTextMessage(message);
}

void WebSocketClient::setNetworkConfig(const QString &interfaceName, bool enable, const QString &mode,
                                     const QString &ipAddress, const QString &netmask, const QString &gateway)
{
    if (!m_connected) {
        emit errorOccurred("未连接到服务器");
        return;
    }

    // 创建请求ID
    QString requestId = QUuid::createUuid().toString(QUuid::WithoutBraces);

    // 创建请求JSON对象
    QJsonObject requestObj;
    requestObj["id"] = requestId;
    requestObj["method"] = "network.setConfig";

    QJsonObject paramsObj;
    paramsObj["interface_name"] = interfaceName;
    paramsObj["enable"] = enable;
    paramsObj["mode"] = mode;

    // 如果是静态IP模式，添加IP配置
    if (mode == "static" && !ipAddress.isEmpty()) {
        QJsonObject ipv4Obj;
        ipv4Obj["address"] = ipAddress;
        ipv4Obj["netmask"] = netmask;
        ipv4Obj["gateway"] = gateway;
        paramsObj["ipv4"] = ipv4Obj;
    }

    requestObj["params"] = paramsObj;

    // 转换为JSON文档
    QJsonDocument doc(requestObj);
    QString message = doc.toJson(QJsonDocument::Compact);

    // 记录这是一个网络配置设置请求
    m_pendingRequests[requestId] = "setNetworkConfig";

    // 发送请求
    m_webSocket.sendTextMessage(message);
}

void WebSocketClient::uploadFirmware(int chunkIndex, int totalChunks, const QByteArray &chunkData,
                                    const QString &fileName, qint64 fileSize, 
                                    const QString &version, const QString &md5)
{
    if (!m_connected) {
        emit errorOccurred("未连接到服务器");
        return;
    }

    // 如果是第一块，重置上传完成标志
    if (chunkIndex == 0) {
        m_firmwareUploadCompleted = false;
    }

    // 创建请求ID
    QString requestId = QUuid::createUuid().toString(QUuid::WithoutBraces);

    // 创建请求JSON对象
    QJsonObject requestObj;
    requestObj["id"] = requestId;
    requestObj["method"] = "firmware.upload";

    QJsonObject paramsObj;
    paramsObj["chunk_index"] = chunkIndex;
    paramsObj["total_chunks"] = totalChunks;
    paramsObj["chunk_data"] = QString(chunkData.toBase64());

    // 如果是第一块，包含文件信息
    if (chunkIndex == 0 && !fileName.isEmpty()) {
        QJsonObject fileInfoObj;
        fileInfoObj["name"] = fileName;
        fileInfoObj["size"] = fileSize;
        if (!version.isEmpty()) {
            fileInfoObj["version"] = version;
        }
        if (!md5.isEmpty()) {
            fileInfoObj["md5"] = md5;
        }
        paramsObj["file_info"] = fileInfoObj;
    }

    requestObj["params"] = paramsObj;

    // 转换为JSON文档
    QJsonDocument doc(requestObj);
    QString message = doc.toJson(QJsonDocument::Compact);

    // 记录这是一个固件上传请求
    m_pendingRequests[requestId] = "uploadFirmware";

    // 发送请求
    m_webSocket.sendTextMessage(message);
}

void WebSocketClient::startFirmwareUpgrade(const QString &version, bool force)
{
    if (!m_connected) {
        emit errorOccurred("未连接到服务器");
        return;
    }

    // 创建请求ID
    QString requestId = QUuid::createUuid().toString(QUuid::WithoutBraces);

    // 创建请求JSON对象
    QJsonObject requestObj;
    requestObj["id"] = requestId;
    requestObj["method"] = "firmware.upgrade";

    QJsonObject paramsObj;
    paramsObj["version"] = version;
    paramsObj["force"] = force;
    requestObj["params"] = paramsObj;

    // 转换为JSON文档
    QJsonDocument doc(requestObj);
    QString message = doc.toJson(QJsonDocument::Compact);

    // 记录这是一个固件升级请求
    m_pendingRequests[requestId] = "startFirmwareUpgrade";

    // 发送请求
    m_webSocket.sendTextMessage(message);
}

void WebSocketClient::getFirmwareUpgradeStatus()
{
    if (!m_connected) {
        emit errorOccurred("未连接到服务器");
        return;
    }

    // 创建请求ID
    QString requestId = QUuid::createUuid().toString(QUuid::WithoutBraces);

    // 创建请求JSON对象
    QJsonObject requestObj;
    requestObj["id"] = requestId;
    requestObj["method"] = "firmware.getStatus";
    requestObj["params"] = QJsonObject();

    // 转换为JSON文档
    QJsonDocument doc(requestObj);
    QString message = doc.toJson(QJsonDocument::Compact);

    // 记录这是一个固件升级状态查询请求
    m_pendingRequests[requestId] = "getFirmwareUpgradeStatus";

    // 发送请求
    m_webSocket.sendTextMessage(message);
}